home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / PowerTalk Access Modules / Sample SMSAM / SampleSMSAM Source / BuildingBlocks / WriteLineWindow.inc1.p < prev    next >
Encoding:
Text File  |  1995-07-28  |  27.2 KB  |  1,263 lines  |  [TEXT/MPS ]

  1. {
  2.     File:        WriteLineWindow.inc1.p
  3.  
  4.     Contains:    Routines to create and handle a scrollable transcript-type window.
  5.                 The expected use of this unit is for a 'debugging' window in an
  6.                 application.
  7.  
  8.                 This unit hooks into the MPW 3.2 i/o hooks, so that once the debugging
  9.                 window is created, all output from Pascal writeln and C printf statements
  10.                 will be placed into this window.
  11.  
  12.     How to use:
  13.                 At the start of your application, call WWInit() and WWNew() or WWNewDefault.
  14.                 This will create and show the debugging window.  In the main event loop,
  15.                 call WWEvent() after you get an event but before you handle it.  If this
  16.                 function returns true, then it was an event associated with the debugging
  17.                 window and should be 'ignored' by your application.
  18.  
  19.                 If you want all information sent to the window also written to a file,
  20.                 call WWRedirect() or WWFSpRedirect.
  21.  
  22.                 To temporarily suspend output from you application, call the WWForce()
  23.                 function.  This saves the current options on a stack and uses the new
  24.                 ones.  When you are ready to restore the old options, call WWEndForce().
  25.  
  26.                 You can call WWAddText() to add text to the window directly.
  27.  
  28.     Written by:    Bruce Horn, Steve Capps, Larry Kenyon,
  29.                 John Meier, scott douglass, Darin Adler,
  30.                 Paul Mercer, Bryan Stearns, Dave Owens
  31.  
  32.     Stolen from the Finder by: Keith Stattenfield
  33.  
  34.     Copyright:    © 1990, 1991 by Apple Computer, Inc., all rights reserved.
  35.  
  36.     Change History:
  37.  
  38.         3/23/93     KSS        Change a bunch of integer's to longint's, so that the window can have more than 32K of text.
  39.         11/23/92    KSS        Don't allocate window data in system heap.
  40.         3/9/92      KSS        Make the default deubg window a bit bigger.
  41.         11/25/91    KSS        Periodically flush the file.
  42.         10/30/91    KSS        Add stuff to set end of file.
  43.  
  44.                  7/25/91    KSS        Added WWNewDefault, WWFSpRedirect, some primitives to insert
  45.                                      and a few 'standard' data types into the window.  Wrote the
  46.                                     Contains: and How to use: sections of this header.
  47.  
  48.          <5>    10/16/90    sad        fix WWRedirect
  49.          <4>      8/3/90    pm        use NewHandleSys instead of NewHandle to make the memory
  50.                                     difference between debug & SCM builds smaller
  51.         <2+>     3/21/90    prp        Debug window's line array memory is allocated by NewHandleClear
  52.                                     instead NewHandle.
  53.  
  54.     To Do:
  55. }
  56.  
  57. {$R-}
  58. {$D+}
  59.  
  60. CONST
  61.     kWWHMargin = 5;
  62.     kWWVMargin = 10;
  63.  
  64.     _CODEV = 1;         {console device number}
  65.  
  66. TYPE    HText = ^PText;
  67.         PText = ^AText;
  68.         AText = PACKED ARRAY [0..10000] OF CHAR;
  69.  
  70.         HLineLens = ^PLineLens;
  71.         PLineLens = ^ALineLens;
  72.         ALineLens = ARRAY[0..10000] OF LONGINT;
  73.  
  74.         ForceState = RECORD
  75.             toWindow:    BOOLEAN;
  76.             toFile:     BOOLEAN;
  77.             END;
  78.  
  79.     IEFilePath =    STRING;
  80.     IEFilePathPtr = ^IEFilePath;
  81.  
  82.     IEFRefNum =     LONGINT;
  83.  
  84. VAR gLines:         INTEGER;                        {number of lines saved}
  85.     gPerLine:        INTEGER;                        {number of characters per line}
  86.     gTotal:         LONGINT;                        {number of characters in all lines together}
  87.     gText:            HText;                            {the ring buffer: blanks pad each line to 80 chars}
  88.     gLineLens:        HLineLens;                        {# of real characters in each line; gLinesLens^^[0]
  89.                                                         is # of characters in the line that begins with
  90.                                                         gText^^[0]}
  91.  
  92.     gFirst:         LONGINT;                        {where in the ring buffer the top line starts}
  93.     gLast:            LONGINT;                        {where in the ring buffer the bottom line starts}
  94.     gPos:            INTEGER;                        {number of characters so far in the bottom line}
  95.  
  96.     gHeight:        INTEGER;                        {font height}
  97.     gLnAscent:        INTEGER;                        {font ascent}
  98.     gWidMax:        INTEGER;                        {font char width (must be monospaced)}
  99.     gSBars:         ARRAY[VHSelect] OF ControlHandle;    {the window scroll bars}
  100.     gScrollOffset:    Point;                            {the position to which we are scrolled}
  101.     gViewSize:        Point;                            {total view size}
  102.     gEndOfText:     Point;                            {the pen position after drawing all the lines}
  103.  
  104.     gStdDrag:        Rect;
  105.     gStdSize:        Rect;
  106.     gOrthogonal:    ARRAY[VHSelect] OF VHSelect;
  107.     gWRec:            WindowRecord;
  108.     gARgn:            RgnHandle;
  109.  
  110.     gGotRefNum:     BOOLEAN;
  111.     gRefNum:        INTEGER;                    {refNum for redirect output}
  112.     gVRefNum:        INTEGER;                    {likewise, vrefNum}
  113.  
  114.     gForceStack:    ARRAY[1..kForceDepth] OF ForceState;
  115.     gForcePtr:        INTEGER;
  116.  
  117.     gHexStr:        String[18];
  118.     gScrollWindowWhenTextIsAdded : boolean;
  119.  
  120. FUNCTION  GetSaveVisRgn: RgnHandle; FORWARD;
  121.  
  122. PROCEDURE WWInstall; FORWARD;
  123. FUNCTION  WWBaseLine(ln: INTEGER): LONGINT; FORWARD;
  124. PROCEDURE WWDoScrolling; FORWARD;
  125. PROCEDURE WWDraw; FORWARD;
  126. PROCEDURE WWNewLine; FORWARD;
  127. PROCEDURE WWShowPoint(pt: Point); FORWARD;
  128. PROCEDURE WWTrackScroll(aControl: ControlHandle; partCode: INTEGER); FORWARD;
  129.  
  130.  
  131. {$S WWSeg}
  132. FUNCTION WWFirstLGlob: LongInt;
  133. BEGIN WWFirstLGlob := ORD(@gLines); END;
  134.  
  135. {$S WWSeg}
  136. FUNCTION WWLastLGlob: LongInt;
  137. BEGIN WWLastLGlob := ORD(@gForcePtr); END;
  138.  
  139. {$S WWSeg}
  140. FUNCTION WWFirstGlob: LongInt;
  141. BEGIN WWFirstGlob := ORD(@gDebugWindowPtr); END;
  142.  
  143. {$S WWSeg}
  144. FUNCTION WWLastGlob: LongInt;
  145. BEGIN WWLastGlob := ORD(@gWrToFile); END;
  146.  
  147.  
  148. {$S WWSeg}
  149. FUNCTION  GetSaveVisRgn: RgnHandle;
  150.     CONST    addr    =    $09F2;
  151.     TYPE    pRgn = ^RgnHandle;
  152.     VAR     pSaveVisRgn:    pRgn;
  153. BEGIN
  154.     pSaveVisRgn := pRgn(addr);
  155.     GetSaveVisRgn := pSaveVisRgn^;
  156. END;
  157.  
  158.  
  159. {$S WWSeg}
  160. FUNCTION  LongerSide(VAR r: Rect): VHSelect;
  161. BEGIN
  162.     WITH r DO
  163.         IF (bottom - top) >= (left - right) THEN
  164.             LongerSide := v
  165.         ELSE
  166.             LongerSide := h;
  167. END;
  168.  
  169.  
  170. {$S WWSeg}
  171. PROCEDURE WindowFocus;
  172. BEGIN
  173.     SetPort(gDebugWindowPtr);
  174.     SetOrigin(0, 0);
  175.     ClipRect(thePort^.portRect);
  176. END;
  177.  
  178.  
  179. {$S WWSeg}
  180. PROCEDURE ContentFocus;
  181.     VAR r:    Rect;
  182. BEGIN
  183.     SetPort(gDebugWindowPtr);
  184.     SetOrigin(gScrollOffset.h, gScrollOffset.v);
  185.     r := thePort^.portRect;
  186.     WITH r DO
  187.         BEGIN
  188.         right := right - 15;
  189.         bottom := bottom - 15;
  190.         END;
  191.     ClipRect(r);
  192. END;
  193.  
  194.  
  195. {$S WWInit}
  196. PROCEDURE WWInit(numLines, numCharsPerLine: INTEGER);
  197.     VAR i: INTEGER;
  198. BEGIN
  199.     gDebugWindowPtr := NIL;
  200.  
  201.     gGotRefNum := FALSE;
  202.     gWrToWindow := TRUE;
  203.     gWrToFile := TRUE;
  204.     gScrollWindowWhenTextIsAdded := false;
  205.     WWInstall;
  206.  
  207.     gForcePtr := 0;
  208.  
  209.     gLines := numLines;
  210.     gPerLine := numCharsPerLine;
  211.     gTotal := gLines * gPerLine;
  212.  
  213.     gText := HText(NewHandleClear(gTotal));
  214.     IF gText = NIL THEN
  215.         BEGIN
  216.         WriteLn('Not enough memory to allocate the Debug Window''s Line Array: ', gLines:1, '*', gPerLine:1);
  217.         EXIT(WWInit);
  218.         END;
  219.  
  220.     gLineLens := HLineLens(NewHandle(gLines*SIZEOF(LONGINT)));
  221.     IF gLineLens = NIL THEN
  222.         BEGIN
  223.         DisposeHandle(Handle(gText));
  224.         WriteLn('Not enough memory to allocate the Debug Window''s LineLen Array: ', gLines:1);
  225.         EXIT(WWInit);
  226.         END;
  227.  
  228.     FOR i := 0 TO gLines-1 DO
  229.         gLineLens^^[i] := 0;
  230.  
  231.     gFirst := 0;
  232.     gLast := gTotal - gPerLine;
  233.     gPos := 0;
  234.  
  235.     gOrthogonal[v] := h;
  236.     gOrthogonal[h] := v;
  237.  
  238.     gHexStr := '0123456789ABCDEF';
  239. END;
  240.  
  241.  
  242. {$S WWInit}
  243. PROCEDURE WWNew(bounds: Rect; windowTitle: Str255; goAway: BOOLEAN; visible: BOOLEAN;
  244.                 outputFont, outputSize: INTEGER);
  245.     VAR fInfo:        FontInfo;
  246.         control:    ControlHandle;
  247.         i:            INTEGER;
  248.         aLine:        StringHandle;
  249.         vhs:        VHSelect;
  250.         savePort:    GrafPtr;
  251. BEGIN
  252.     GetPort(savePort);
  253.     IF gDebugWindowPtr = NIL THEN
  254.         BEGIN
  255.         gDebugWindowPtr := NewWindow(nil, bounds, windowTitle, visible, documentProc,
  256.                                     POINTER(-1), goAway, 0);
  257.  
  258.         WITH screenBits.bounds DO
  259.             BEGIN
  260.             SetRect(gStdDrag, 4, 24, right - 4, bottom - 4);    {this is suggested in Inside Macintosh}
  261.             SetRect(gStdSize, 20, 20, right, bottom - 20);        {arbitrary Minimum size; Maximum size is screen}
  262.             END;
  263.  
  264.         gARgn := NewRgn;
  265.  
  266.         SetPt(gEndOfText, kWWHMargin, WWBaseLine(gLines));
  267.  
  268.         SetPort(gDebugWindowPtr);
  269.         TextFont(outputFont);
  270.         TextSize(outputSize);
  271.         GetFontInfo(fInfo);
  272.  
  273.         WITH fInfo DO
  274.             BEGIN
  275.             gHeight := ascent + descent + leading;
  276.             gLnAscent := ascent;
  277.             gWidMax := widMax;
  278.             SetPt(gViewSize, (2 * kWWHMargin) + (gPerLine * widMax), (2 * kWWVMargin) + (gHeight * gLines));
  279.             END;
  280.  
  281.         {scroll bars}
  282.         FOR vhs := v TO h DO
  283.             gSBars[vhs] := NewControl(gDebugWindowPtr, gDebugWindowPtr^.portRect, '', FALSE,
  284.                                 0, 0, 1, scrollBarProc, 0);
  285.  
  286.         {SetPt(gScrollOffset, 0, 0);}
  287.         gScrollOffset := Point(longint(0));
  288.  
  289.         {put the scroll bars in the right place}
  290.         WWGrown;
  291.  
  292.         {force an update}
  293.         WWUpdateEvent;
  294.  
  295.         {scroll to the end, in case there is some information that needs to be displayed}
  296.         SetCtlValue(gSBars[v], MAXINT);
  297.         WWDoScrolling;
  298.         END;
  299.     SetPort(savePort);
  300. END;
  301.  
  302. {$S WWInit}
  303. PROCEDURE WWNewDefault;
  304. VAR
  305.     aRect    :    Rect;
  306.     title : Str255;
  307. BEGIN
  308.     SetRect (aRect, 620, 40, 1040, 860);
  309.  
  310.     SetRect (aRect, 16, 40, 16+6*80+16, 40+12*36);
  311.     title := concat(StringPtr(CurApName)^, ' Debug Window');
  312.     WWNew (aRect, title, true, true, 1, 9);
  313. END;
  314.  
  315.  
  316.  
  317. {$S WWSeg}
  318. PROCEDURE WWActivateEvent(modifiers: INTEGER);
  319.     VAR r:            Rect;
  320.         vhs:        VHSelect;
  321.         anSBar:     ControlHandle;
  322.         savePort:    GrafPtr;
  323. BEGIN
  324.     GetPort(savePort);
  325.  
  326.     WindowFocus;
  327.  
  328.     r := thePort^.portRect;
  329.  
  330.     FOR vhs := v TO h DO
  331.         BEGIN
  332.         anSBar := gSBars[vhs];
  333.         IF Odd(modifiers) THEN
  334.             ShowControl(anSBar)
  335.         ELSE
  336.             HideControl(anSBar);
  337.         END;
  338.  
  339.     DrawGrowIcon(gDebugWindowPtr);
  340.  
  341.     SetPort(savePort);
  342. END;
  343.  
  344.  
  345. {$S WWSeg}
  346. PROCEDURE WWAddText(textBuf: Ptr; byteCount: longint);
  347.     CONST BS = 8;
  348.     VAR gotEOL:     BOOLEAN;
  349.         b:            QDByte;
  350.         startPtr:    Ptr;
  351.         startCount: INTEGER;
  352.         ps:         PenState;
  353.         savePort:    GrafPtr;
  354.         deleted:    BOOLEAN;
  355.         r:            Rect;
  356.  
  357.         count:        LONGINT;
  358.         err : OSErr;
  359.         filePos : longint;
  360. BEGIN
  361.     IF gWrToFile THEN
  362.         IF gGotRefNum THEN
  363.             BEGIN
  364.             count := byteCount;
  365.             IF FSWrite(gRefNum, count, textBuf) <> noErr THEN
  366.                 BEGIN
  367.                 {??? do something here ???}
  368.                 END;
  369.             if GetFPos (gRefNum, filePos) = noErr then
  370.                 if SetEOF (gRefNum, filePos) = noErr then
  371.                     WWFlushOutputFile;
  372.             END;
  373.  
  374.     IF gWrToWindow THEN
  375.         BEGIN
  376.         IF gDebugWindowPtr <> NIL THEN
  377.             GetPort(savePort);
  378.  
  379.         deleted := FALSE;
  380.  
  381.         WHILE byteCount > 0 DO
  382.             BEGIN
  383.             gotEOL := FALSE;
  384.             startPtr := textBuf;
  385.             startCount := byteCount;
  386.  
  387.             WHILE (byteCount > 0) AND (gPos < gPerLine) AND (NOT gotEOL) DO
  388.                 BEGIN
  389.                 b := QDPtr(textBuf)^;
  390.                 byteCount := byteCount - 1;
  391.                 textBuf := Ptr(LONGINT(textBuf) + 1);
  392.  
  393.                 IF b = ORD(kWWEol) THEN
  394.                     gotEOL := TRUE
  395.                 ELSE IF b <> BS THEN
  396.                     BEGIN
  397.                     gText^^[gLast+gPos] := CHAR(b);
  398.                     gPos := gPos + 1;
  399.                     END
  400.                 ELSE IF gPos > 0 THEN  {Backspace -- don't backspace past beginning of line!}
  401.                     BEGIN
  402.                     WITH gEndOfText DO
  403.                         BEGIN
  404.                         SetRect(r, h - gWidMax, v - gLnAscent, h, v + gHeight - gLnAscent);
  405.                         h := h - gWidMax;
  406.                         END;
  407.  
  408.                     IF gDebugWindowPtr <> NIL THEN
  409.                         BEGIN
  410.                         ContentFocus;
  411.                         EraseRect(r);
  412.                         END;
  413.  
  414.                     gPos := gPos - 1;
  415.                     deleted := TRUE;
  416.                     END
  417.                 ELSE
  418.                     deleted := TRUE;
  419.                 END;
  420.  
  421.             IF NOT deleted AND (gDebugWindowPtr <> NIL) THEN
  422.                 BEGIN
  423.                 ContentFocus;
  424.                 MoveTo(gEndOfText.h, gEndOfText.v);
  425.                 DrawText(QDPtr(startPtr), 0, startCount - byteCount - ORD(gotEOL));
  426.                 GetPenState(ps);
  427.                 gEndOfText := ps.pnLoc;
  428.                 END;
  429.  
  430.             IF (gPos >= gPerLine) OR gotEOL THEN
  431.                 BEGIN
  432.                 gLineLens^^[gLast DIV gPerLine] := gPos;    {remember # characters in this line}
  433.  
  434.                 WWNewLine;
  435.                 IF (byteCount > 0) AND (NOT gotEOL) THEN
  436.                     BEGIN
  437.                     gText^^[gLast] := '…';
  438.                     gPos := 1;
  439.                     END;
  440.                 END;
  441.             END;
  442.  
  443.         gLineLens^^[gLast DIV gPerLine] := gPos;
  444.  
  445.         IF gDebugWindowPtr <> NIL THEN
  446.             SetPort(savePort);
  447.         END;
  448. END;
  449.  
  450. PROCEDURE WWFlushOutputFile;
  451. var
  452.     pb    :    ParamBlockRec;
  453. BEGIN
  454.     if gWrToFile then
  455.         begin
  456.         pb.ioCompletion := nil;
  457.         pb.ioRefNum := gRefNum;
  458.         if PBFlushFile(@pb, false) = noErr then
  459.             ;
  460.         end;
  461. END;
  462.  
  463.  
  464. {$S WWSeg}
  465. FUNCTION  WWBaseLine(ln: INTEGER): LONGINT;
  466. BEGIN
  467.     WWBaseLine := kWWVMargin + (ln - 1) * gHeight;
  468. END;
  469.  
  470.  
  471. {$S WWSeg}
  472. PROCEDURE WWDoScrolling;
  473.     VAR newOffset:        Point;
  474.         delta:            Point;
  475. BEGIN
  476.     newOffset.v := GetCtlValue(gSBars[v]);
  477.     delta.v := gScrollOffset.v - newOffset.v;
  478.     newOffset.h := GetCtlValue(gSBars[h]);
  479.     delta.h := gScrollOffset.h - newOffset.h;
  480.  
  481.     IF (delta.h <> 0) OR (delta.v <> 0) THEN
  482.         BEGIN
  483.         ContentFocus;
  484.  
  485.         ScrollRect(thePort^.portRect, delta.h, delta.v, gARgn);
  486.         gScrollOffset := newOffset;
  487.  
  488.         InvalRgn(gARgn);
  489.  
  490.         WWUpdateEvent;
  491.         END;
  492. END;
  493.  
  494.  
  495. {$S WWSeg}
  496. PROCEDURE WWDraw;
  497.     VAR i:        INTEGER;
  498.         y:        INTEGER;
  499.         start:    LONGINT;
  500.         line:    INTEGER;
  501.         ps:     PenState;
  502. BEGIN
  503.     y := kWWVMargin;            {initial y corodinate}
  504.  
  505.     start := gFirst;            {offset to first character of next line to draw}
  506.     line := start DIV gPerLine; {index into gLineLens array for next line to draw; always start DIV gPerLine}
  507.  
  508.     FOR i := 1 TO gLines DO
  509.         BEGIN
  510.         MoveTo(kWWHMargin, y);
  511.  
  512.         HLock(Handle(gText));
  513.         DrawText(QDPtr(gText^), start, gLineLens^^[line]);
  514.         HUnlock(Handle(gText));
  515.  
  516.         y := y + gHeight;
  517.         start := start + gPerLine;
  518.         line := line + 1;
  519.  
  520.         IF start = gTotal THEN
  521.             BEGIN
  522.             start := 0;
  523.             line := 0;
  524.             END;
  525.         END;
  526.  
  527.     GetPenState(ps);            {remember position of last character drawn}
  528.     gEndOfText := ps.pnLoc;
  529. END;
  530.  
  531.  
  532. {$S WWSeg}
  533. PROCEDURE WWEndForce;
  534. BEGIN
  535.     IF gForcePtr <= 0 THEN
  536.         BEGIN
  537.         END
  538.     ELSE
  539.         BEGIN
  540.         WITH gForceStack[gForcePtr] DO
  541.             BEGIN
  542.             gWrToWindow := toWindow;
  543.             gWrToFile := toFile;
  544.             END;
  545.         gForcePtr := gForcePtr - 1;
  546.         END;
  547. END;
  548.  
  549.  
  550. {$S WWSeg}
  551. PROCEDURE WWForceOutput(wrToWindow, wrToFile: WrForceOptions);
  552. BEGIN
  553.     IF gForcePtr >= kForceDepth THEN
  554.         BEGIN
  555.         END
  556.     ELSE
  557.         BEGIN
  558.         gForcePtr := gForcePtr + 1;
  559.  
  560.         WITH gForceStack[gForcePtr] DO
  561.             BEGIN
  562.             toWindow := gWrToWindow;
  563.             toFile := gWrToFile;
  564.             END;
  565.  
  566.         IF wrToWindow <> forceUnchanged THEN
  567.             gWrToWindow := wrToWindow = forceOn;
  568.  
  569.         IF wrToFile <> forceUnchanged tHEN
  570.             gWrToFile := wrToFile = forceOn;
  571.         END;
  572. END;
  573.  
  574.  
  575. {$S WWSeg}
  576. PROCEDURE WWGrown;
  577.     VAR r:                Rect;
  578.         vhs:            VHSelect;
  579.         anSBar:         ControlHandle;
  580.         newMax:         INTEGER;
  581.         isVisible:        BOOLEAN;
  582.         savePort:        GrafPtr;
  583. BEGIN
  584.     GetPort(savePort);
  585.  
  586.     WindowFocus;
  587.     r.topLeft := Point(longint(0));
  588.     r.botRight := Point(longint(0));
  589.     ClipRect(r);
  590.  
  591.     FOR vhs := v TO h DO
  592.         BEGIN
  593.         anSBar := gSBars[vhs];
  594.  
  595.         r := thePort^.portRect;
  596.  
  597.         WITH r DO
  598.             BEGIN
  599.             {Calculate new position of scroll bar}
  600.             topLeft.vh[vhs] := topLeft.vh[vhs] - 1;
  601.             topLeft.vh[gOrthogonal[vhs]] := botRight.vh[gOrthogonal[vhs]] - 15;
  602.             botRight.vh[vhs] := botRight.vh[vhs] - 14;
  603.             botRight.vh[gOrthogonal[vhs]] := topLeft.vh[gOrthogonal[vhs]] + 16;
  604.  
  605.             {Move the scroll bar}
  606.             MoveControl(anSBar, left, top);
  607.             SizeControl(anSBar, right-left, bottom-top);
  608.  
  609.             newMax := gViewSize.vh[vhs] - (bottom - top);
  610.             IF newMax < 0 THEN
  611.                 newMax := 0;
  612.             SetCtlMax(anSBar, newMax);
  613.             END;
  614.         END;
  615.  
  616.     WWInvalGrowBox;
  617.  
  618.     WWDoScrolling;    {in case we are showing too much white space}
  619.  
  620.     SetPort(savePort);
  621. END;
  622.  
  623.  
  624. {$S WWSeg}
  625. PROCEDURE WWInvalGrowBox;
  626.     VAR r:    Rect;
  627. BEGIN
  628.     r.botRight := thePort^.portRect.botRight;
  629.     WITH r DO
  630.         BEGIN
  631.         top := bottom - 15;
  632.         left := right - 15;
  633.         END;
  634.     InvalRect(r);
  635. END;
  636.  
  637.  
  638. {$S WWSeg}
  639. PROCEDURE WWMouseDown(where: INTEGER; pt: Point; modifiers: INTEGER);
  640.     VAR r:                Rect;
  641.         sizeStuff:        RECORD CASE INTEGER OF
  642.                             1:    (growResult: LONGINT);        {Information returned by GrowRect}
  643.                             2:    (newV,                        {new vertical size}
  644.                                  newH: INTEGER);            {new horizontal size}
  645.                             3:    (newSize: Point);            {new size as a point}
  646.                         END;
  647.         partCode:        INTEGER;
  648.         whichControl:    ControlHandle;
  649.         oldSize:        Point;
  650.         savePort:        GrafPtr;
  651. BEGIN
  652.     GetPort(savePort);
  653.  
  654.     CASE where OF
  655.         inDrag:
  656.             DragWindow(gDebugWindowPtr, pt, gStdDrag);
  657.  
  658.         inGrow:
  659.             BEGIN
  660.             WindowFocus;
  661.  
  662.             WITH sizeStuff DO
  663.                 BEGIN
  664.                 WITH gDebugWindowPtr^.portRect, oldSize DO
  665.                     BEGIN
  666.                     h := right - left;
  667.                     v := bottom - top;
  668.                     END;
  669.  
  670.                 growResult := GrowWindow(gDebugWindowPtr, pt, gStdSize);
  671.                 IF growResult <> 0 THEN
  672.                     BEGIN
  673.                     WWInvalGrowBox;
  674.                     SizeWindow(gDebugWindowPtr, newH, newV, TRUE);
  675.                     WWGrown;
  676.                     END;
  677.                 END;
  678.             END;
  679.  
  680.         inGoAway:
  681.             IF TrackGoAway(gDebugWindowPtr, pt) THEN
  682.                 HideWindow(gDebugWindowPtr);
  683.  
  684.         inContent:
  685.             IF gDebugWindowPtr = FrontWindow THEN
  686.                 BEGIN
  687.                 WindowFocus;
  688.  
  689.                 GlobalToLocal(pt);
  690.                 partCode := FindControl(pt, gDebugWindowPtr, whichControl);
  691.                 IF partCode <> 0 THEN
  692.                     CASE partCode OF
  693.                         inUpButton, inDownButton, inPageUp, inPageDown:
  694.                             partCode := TrackControl(whichControl, pt, @WWTrackScroll);
  695.                         inThumb:
  696.                             BEGIN
  697.                             partCode := TrackControl(whichControl, pt, NIL);
  698.                             WWDoScrolling;
  699.                             END;
  700.                         END;
  701.                 END
  702.             ELSE
  703.                 SelectWindow(gDebugWindowPtr);
  704.         END;  {CASE}
  705.  
  706.     SetPort(savePort);
  707. END;
  708.  
  709.  
  710. {$S WWSeg}
  711. PROCEDURE WWNewLine;
  712.     VAR savePort:        GrafPtr;
  713.         i:                INTEGER;
  714.         pt:             Point;
  715.         r:                Rect;
  716. BEGIN
  717.     GetPort(savePort);
  718.  
  719.     SetPt(pt, kWWHMargin, gEndOfText.v);
  720.  
  721.     if gScrollWindowWhenTextIsAdded then
  722.         WWShowPoint(pt);
  723.  
  724.     gLast := gFirst;
  725.     gPos := 0;
  726.     gLineLens^^[gLast DIV gPerLine] := gPos;    {remember # characters in new line}
  727.  
  728.     gFirst := gFirst + gPerLine;
  729.     IF gFirst = gTotal THEN
  730.         gFirst := 0;
  731.  
  732.     SetPt(gEndOfText, kWWHMargin, WWBaseLine(gLines));
  733.  
  734.     IF gDebugWindowPtr <> NIL THEN
  735.         BEGIN
  736.         ContentFocus;
  737.         SetRect(r, kWWHMargin, kWWVMargin - gLnAscent, gViewSize.h, gEndOfText.v + gHeight - gLnAscent);
  738.         ScrollRect(r, 0, -gHeight, gARgn);
  739.         InvalRgn(gARgn);
  740.  
  741.         WWUpdateEvent;
  742.         END;
  743.  
  744.     SetPort(savePort);
  745. END;
  746.  
  747.  
  748. FUNCTION  WWRedirect(vRefNum: INTEGER; fileName: Str255): OSErr;
  749.     VAR err:    OSErr;
  750.         append: BOOLEAN;
  751.         x:        LONGINT;
  752. BEGIN
  753.     IF gGotRefNum THEN
  754.         BEGIN
  755.             {truncate the file to current position}
  756.         err := GetFPos(gRefNum, x);
  757.         err := SetEOF(gRefNum, x);
  758.  
  759.         IF FSClose(gRefNum) <> noErr THEN {??? error closing file ???};
  760.         IF FlushVol(NIL, gVRefNum) <> noErr THEN {??? Another fine mess ???};
  761.         gGotRefNum := FALSE;
  762.         END;
  763.  
  764.     append := POS('>>', fileName) = 1;
  765.     IF append THEN
  766.         Delete(fileName, 1 ,2);
  767.  
  768.     IF fileName <> '' THEN
  769.         BEGIN
  770.         err := Create(fileName, vRefNum, 'MACA', 'TEXT');
  771.  
  772.         IF (err = noErr) OR (err = dupFNErr) THEN
  773.             BEGIN
  774.             err := FSOpen(fileName, vRefNum, gRefNum);
  775.             gVRefNum := vRefNum;
  776.             WWRedirect := err;
  777.  
  778.             gGotRefNum := err = noErr;
  779.  
  780.             IF gGotRefNum THEN
  781.                 IF append THEN
  782.                     BEGIN
  783.                     err := GetEOF(gRefNum, x);
  784.                     err := SetFPos(gRefNum, fsFromStart, x);
  785.                     END
  786.                 else
  787.                     err := SetEOF (gRefNum, 0);
  788.             END
  789.         ELSE
  790.             WWRedirect := err;
  791.         END
  792.     ELSE
  793.         WWRedirect := noErr;
  794. END;
  795.  
  796. FUNCTION  WWFSpRedirect(redirectFile : FSSpec; appendToExistingFile : boolean ): OSErr;
  797.     VAR err:    OSErr;
  798.         append: BOOLEAN;
  799.         x:        LONGINT;
  800. BEGIN
  801.     IF gGotRefNum THEN
  802.         BEGIN
  803.             {truncate the file to current position}
  804.         err := GetFPos(gRefNum, x);
  805.         err := SetEOF(gRefNum, x);
  806.  
  807.         IF FSClose(gRefNum) <> noErr THEN {??? error closing file ???};
  808.         IF FlushVol(NIL, gVRefNum) <> noErr THEN {??? Another fine mess ???};
  809.         gGotRefNum := FALSE;
  810.         END;
  811.  
  812.     if (redirectFile.vRefNum = 0) & (redirectFile.parID = 0) then
  813.         err := FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder, redirectFile.vRefNum, redirectFile.parID);
  814.  
  815.     IF redirectFile.name <> '' THEN
  816.         BEGIN
  817.         err := FSpCreate(redirectFile, 'MACA', 'TEXT', smRoman);
  818.  
  819.         IF (err = noErr) OR (err = dupFNErr) THEN
  820.             BEGIN
  821.             err := FSpOpenDF(redirectFile, fsRdWrPerm, gRefNum);
  822.             gVRefNum := redirectFile.vRefNum;
  823.             WWFSpRedirect := err;
  824.  
  825.             gGotRefNum := (err = noErr);
  826.  
  827.             IF gGotRefNum THEN
  828.                 IF appendToExistingFile THEN
  829.                     BEGIN
  830.                     err := GetEOF(gRefNum, x);
  831.                     err := SetFPos(gRefNum, fsFromStart, x);
  832.                     END;
  833.             END
  834.         ELSE
  835.             WWFSpRedirect := err;
  836.         END
  837.     ELSE
  838.         WWFSpRedirect := noErr;
  839. END;
  840.  
  841.  
  842. PROCEDURE WWScroll(howManyLines: INTEGER);
  843.     VAR val:        INTEGER;
  844.         savePort:    GrafPtr;
  845. BEGIN
  846.     GetPort(savePort);
  847.     val := GetCtlValue(gSBars[v]);
  848.     IF ((howManyLines < 0) AND (val > GetCtlMin(gSBars[v]))) OR
  849.        ((howManyLines > 0) AND (val < GetCtlMax(gSBars[v]))) THEN
  850.         BEGIN
  851.         SetCtlValue(gSBars[v], val + howManyLines * gHeight);
  852.         WWDoScrolling;
  853.         END;
  854.     SetPort(savePort);
  855. END;
  856.  
  857.  
  858. PROCEDURE WWShowPoint(pt: Point);
  859.     VAR minToSee:    Point;
  860.         deltaCd:    INTEGER;
  861. BEGIN
  862.     IF gDebugWindowPtr <> NIL THEN
  863.         BEGIN
  864.         WindowFocus;
  865.  
  866.         SetPt(minToSee, 50, gHeight);
  867.  
  868.         {the following code is actually better than writing a loop with VHSelect}
  869.         WITH thePort^.portRect DO
  870.             BEGIN
  871.             deltaCd := pt.v + mintoSee.v - (bottom - 15 + gScrollOffset.v);
  872.             IF deltaCd <= 0 THEN
  873.                 BEGIN
  874.                 deltaCd := pt.v - minToSee.v - (top + gScrollOffset.v);
  875.                 IF deltaCd >= 0 THEN
  876.                     deltaCd := 0;
  877.                 END;
  878.             SetCtlValue(gSBars[v], GetCtlValue(gSBars[v]) + deltaCd);
  879.  
  880.             deltaCd := pt.h + mintoSee.h - (right - 15 + gScrollOffset.h);
  881.             IF deltaCd <= 0 THEN
  882.                 BEGIN
  883.                 deltaCd := pt.h - minToSee.h - (left + gScrollOffset.h);
  884.                 IF deltaCd >= 0 THEN
  885.                     deltaCd := 0;
  886.                 END;
  887.             SetCtlValue(gSBars[h], GetCtlValue(gSBars[h]) + deltaCd);
  888.             END;
  889.  
  890.         WWDoScrolling;
  891.         END;
  892. END;
  893.  
  894.  
  895. {$S WWSeg}
  896. PROCEDURE WWTrackScroll(aControl: ControlHandle; partCode: INTEGER);
  897.     VAR up:         BOOLEAN;
  898.         ctlValue:    INTEGER;
  899.         vhs:        VHSelect;
  900.         r:            Rect;
  901.         delta:        INTEGER;
  902. BEGIN
  903.     IF partCode <> 0 THEN
  904.         BEGIN
  905.         up := (partCode = inUpButton) OR (partCode = inPageUp);
  906.         ctlValue := GetCtlValue(aControl);
  907.  
  908.       {avoid flicker in setting thumb, IF user tries to scroll past end}
  909.         IF (up AND (ctlValue > GetCtlMin(aControl))) OR
  910.            (NOT up AND (ctlValue < GetCtlMax(aControl))) THEN
  911.             BEGIN
  912.             r := aControl^^.contrlRect;   {heap may compact when we call LongerSide}
  913.             vhs := LongerSide(r);          {this tells us which way we are scrolling}
  914.  
  915.             IF (partCode = inPageUp) OR (partCode = inPageDown) THEN
  916.                 WITH gDebugWindowPtr^.portRect DO
  917.                     delta := botRight.vh[vhs] - topLeft.vh[vhs] - gHeight
  918.             ELSE
  919.                 delta := gHeight;
  920.  
  921.             IF up THEN
  922.                 delta := - delta;
  923.  
  924.             SetCtlValue(aControl, ctlValue + delta);
  925.             WWDoScrolling;
  926.  
  927.             WindowFocus;
  928.             END;
  929.         END;
  930. END;
  931.  
  932.  
  933. {$S WWSeg}
  934. PROCEDURE WWUpdateEvent;
  935.     VAR savePort:        GrafPtr;
  936.         saveSaveVisRgn: RgnHandle;
  937.         saveVisRgn:     RgnHandle;
  938. BEGIN
  939.     if (gDebugWindowPtr <> NIL) AND (NOT EmptyRgn(WindowPeek(gDebugWindowPtr)^.port.visRgn)) THEN BEGIN
  940.  
  941.         GetPort(savePort);
  942.  
  943.         saveSaveVisRgn := NewRgn;
  944.         saveVisRgn := GetSaveVisRgn;
  945.  
  946.         CopyRgn(saveVisRgn, saveSaveVisRgn);
  947.  
  948.         BeginUpdate(gDebugWindowPtr);
  949.  
  950.         WindowFocus;
  951.  
  952.         EraseRect(thePort^.portRect);
  953.  
  954.         DrawGrowIcon(gDebugWindowPtr);
  955.         DrawControls(gDebugWindowPtr);
  956.  
  957.         ContentFocus;
  958.         WWDraw;
  959.  
  960.         EndUpdate(gDebugWindowPtr);
  961.  
  962.         CopyRgn(saveSaveVisRgn, saveVisRgn);
  963.         DisposeRgn(saveSaveVisRgn);
  964.  
  965.         SetPort(savePort);
  966.     END;
  967. END;
  968.  
  969.  
  970. {$S WWSeg}
  971. FUNCTION WWReadCh: CHAR;
  972.     VAR savePort:    GrafPtr;
  973.         ch:         CHAR;
  974.         anEvent:    EventRecord;
  975.         r:            Rect;
  976. BEGIN
  977.     GetPort(savePort);
  978.  
  979.     ContentFocus;
  980.  
  981.     WITH gEndOfText DO
  982.         SetRect(r, h, v - gLnAscent, h + gWidMax, v + gHeight - gLnAscent);
  983.  
  984.     FillRect(r, black);
  985.     REPEAT UNTIL GetOSEvent(keyDownMask+autoKeyMask, anEvent);
  986.     EraseRect(r);
  987.  
  988.     ch := CHAR(BAND(anEvent.message, charCodeMask));
  989.  
  990.     WWReadCh := ch;
  991.  
  992.     SetPort(savePort);
  993. END;
  994.  
  995.  
  996. {$S WWSeg}
  997. FUNCTION WWReadLn(buffer: Ptr; byteCount: INTEGER): LONGINT;
  998.     CONST
  999.         CR = 13;
  1000.         BS = 8;
  1001.     TYPE    PA1000 = PACKED ARRAY [0..999] OF CHAR;
  1002.             StrPtr = ^PA1000;
  1003.     VAR ch:     CHAR;
  1004.         len:        INTEGER;
  1005. BEGIN
  1006.     len := 0;
  1007.     REPEAT
  1008.         ch := WWReadCh;
  1009.         IF ORD(ch) <> BS THEN
  1010.             BEGIN
  1011.             WWAddText(POINTER(ORD(@ch)+1), 1);
  1012.             StrPtr(buffer)^[len] := CHAR(ch);
  1013.             len := len + 1;
  1014.             END
  1015.         ELSE IF len > 0 THEN
  1016.             BEGIN
  1017.             WWAddText(POINTER(ORD(@ch)+1), 1);
  1018.             len := len - 1;
  1019.             StrPtr(buffer)^[len] := ' ';
  1020.             END
  1021.    UNTIL (ORD(ch)=CR) OR (len = byteCount);
  1022.  
  1023.    WWReadLn := len;
  1024. END;
  1025.  
  1026.  
  1027. PROCEDURE IDUWritelnWindow; {Writeln UWritelnWindow's compile time.}
  1028. BEGIN
  1029.     Writeln('UWritelnWindow of ', COMPDATE, ' @ ', COMPTIME);
  1030. END;
  1031.  
  1032.  
  1033. FUNCTION
  1034.     wwFAccess(fName: UNIV IEFilePathPtr; opCode: LONGINT; arg: UNIV LONGINT):
  1035.     LONGINT; C; EXTERNAL;
  1036. FUNCTION
  1037.     wwClose(fdesc: IEFRefNum):
  1038.     LONGINT; C; EXTERNAL;
  1039. FUNCTION
  1040.     wwRead(fdesc: IEFRefNum; bufp: UNIV LONGINT; count: LONGINT):
  1041.     LONGINT; C; EXTERNAL;
  1042. FUNCTION
  1043.     wwWrite(fdesc: IEFRefNum; bufp: UNIV LONGINT; count: LONGINT):
  1044.     LONGINT; C; EXTERNAL;
  1045. FUNCTION
  1046.     wwIoctl(fdesc: IEFRefNum; request: LONGINT; arg: UNIV LONGINT):
  1047.     LONGINT; C; EXTERNAL;
  1048.  
  1049. FUNCTION
  1050.     _addDevHandler(
  1051.         slot, dvName, dvFAccess, dvClose, dvRead, dvWrite, dvIoctl: LONGINT):
  1052.     LONGINT; C; EXTERNAL;
  1053.  
  1054. PROCEDURE WWInstall;
  1055.     VAR slot: LONGINT;
  1056. BEGIN
  1057.     slot := _addDevHandler(_CODEV, 0,
  1058.                     ORD(@wwFAccess), ORD(@wwClose),
  1059.                     ORD(@wwRead), ORD(@wwWrite),
  1060.                     ORD(@wwIoctl));
  1061.     PLsetvbuf(output, NIL, 64, 100);
  1062. END;
  1063.  
  1064.  
  1065. {
  1066. --    Paul's Writeln routines  ----------------------------------------------------------------
  1067. }
  1068. FUNCTION WWEvent(event:EventRecord): Boolean;
  1069.  
  1070. VAR
  1071.     WindowPointedTo: WindowPtr;        {window where the mouse is}
  1072.     MouseLoc:        Point;
  1073.     WindoPart:       Integer;        {component of window where mouse is}
  1074.     MenuHdl:         MenuHandle;    {holds the menuhandle of selected menu}
  1075.  
  1076. BEGIN
  1077.     WWEvent := False;            {set the default}
  1078.  
  1079.     CASE event.what of
  1080.         mouseDown:
  1081.             BEGIN
  1082.                 MouseLoc := event.where;
  1083.                 WindoPart := FindWindow(MouseLoc, WindowPointedTo);
  1084.  
  1085.                 IF  (WindowPointedTo = gDebugWindowPtr) THEN
  1086.                     BEGIN
  1087.                         WWEvent := True;
  1088.  
  1089.                         IF (WindowPointedTo <> FrontWindow)
  1090.                             THEN SelectWindow(WindowPointedTo)
  1091.                         ELSE
  1092.                             WWMouseDown(WindoPart, MouseLoc, Event.modifiers);
  1093.                     END;
  1094.             END;
  1095.  
  1096.         ActivateEvt:
  1097.             IF WindowPtr(Event.message) = gDeBugWindowPtr THEN
  1098.                 BEGIN
  1099.                     WWActivateEvent(Event.modifiers);
  1100.                     WWEvent := True;
  1101.                 END;
  1102.  
  1103.         UpDateEvt:
  1104.             IF WindowPtr(Event.message) = gDeBugWindowPtr THEN
  1105.                 BEGIN
  1106.                     WWUpDateEvent;
  1107.                     WWEvent := True;
  1108.                 END;
  1109.  
  1110.     END; {of CASE}
  1111. END; {FUNCTION WWEvent}
  1112.  
  1113. {
  1114. --    end Writeln routines  ------------------------------------------------------------
  1115. }
  1116.  
  1117. {
  1118. -- Keith's WriteLineWindow routines --------------------------------------------------
  1119. }
  1120. PROCEDURE WWAddDate;
  1121. VAR
  1122.     dateTime : longint;
  1123.     tempStr255 : Str255;
  1124. BEGIN
  1125.     GetDateTime (dateTime);
  1126.     IUDateString(dateTime, shortDate, tempStr255);
  1127.     write (tempStr255, ' ');
  1128. END;
  1129.  
  1130. PROCEDURE WWAddTime;
  1131. VAR
  1132.     dateTime : longint;
  1133.     tempStr255 : Str255;
  1134. BEGIN
  1135.     GetDateTime (dateTime);
  1136.     IUTimeString(dateTime, true, tempStr255);
  1137.     write (tempStr255, ' ');
  1138. END;
  1139.  
  1140. PROCEDURE WWAddDateTime;
  1141. BEGIN
  1142.     WWAddDate;
  1143.     WWAddTime;
  1144. END;
  1145.  
  1146. PROCEDURE WWAddEncodedText (dataPtr : UNIV Ptr; dataSize : integer);
  1147. type
  1148.     BytePtr = ^Byte;            { this is unsigned! }
  1149. VAR
  1150.     index        :    integer;
  1151.     aByte : integer;
  1152. BEGIN
  1153.     for index := 0 to dataSize - 1
  1154.     do
  1155.     begin
  1156.         aByte := BytePtr( ord4(dataPtr) + index)^;
  1157.         case aByte of
  1158.              0, 128:        aByte := ord('ø');
  1159.              8, 136:        aByte := ord('Δ');
  1160.             10, 138:        aByte := ord('◊');
  1161.             13, 141:        aByte := ord('¬');
  1162.             222 :             aByte := ord('∞');        { non-breaking space }
  1163.             33..126:         ;
  1164.             otherwise
  1165.                 aByte := ord('¿');
  1166.         end;
  1167.         write (chr(aByte));
  1168.     end;
  1169. END;
  1170.  
  1171. function IntegerMax (a, b : integer) : integer;
  1172. begin
  1173.     if a < b then
  1174.         IntegerMax := b
  1175.     else
  1176.         IntegerMax := a;
  1177. end;
  1178.  
  1179. FUNCTION NumToHexStringF(theNumber: longint): str255;
  1180.     VAR
  1181.         tempStr: string[16];
  1182.         index: integer;
  1183.         digit1, digit2, digit3 : longint;
  1184.         hexStr : str255;
  1185.         mask : longint;
  1186.     BEGIN
  1187.  
  1188.     tempStr := '00000000';
  1189.  
  1190.     FOR index := 7 downto 0
  1191.     do
  1192.         begin
  1193.         mask := BSL ($F, 4 * index);
  1194.         digit1 := BAND (theNumber, mask);
  1195.         digit2 := BSR (digit1, 4*index);
  1196.         tempStr[8-index] := gHexStr[digit2+1];
  1197.         END;
  1198.  
  1199.     NumToHexStringF := tempStr;
  1200.     END;
  1201.  
  1202. PROCEDURE WWAddHexData (dataPtr : UNIV Ptr; dataSize : integer);
  1203. type
  1204.     BytePtr = ^Byte;            { this is unsigned! }
  1205. VAR
  1206.     offset, index : longint;
  1207.     result : str255;
  1208.     len : integer;
  1209.     byte : integer;
  1210. BEGIN
  1211.     if dataPtr = nil
  1212.     then
  1213.         begin
  1214.         writeln ('No data dump, NIL data ptr');
  1215.         exit (WWAddHexData);
  1216.         end;
  1217.  
  1218.     if dataSize <= 0
  1219.     then
  1220.         begin
  1221.         writeln ('No data dump, datesize <= 0');
  1222.         exit (WWAddHexData);
  1223.         end;
  1224.  
  1225.     offset := 0;
  1226.  
  1227.     while (offset < dataSize) do
  1228.     begin
  1229.         write ( NumToHexStringF (offset), ':');
  1230.  
  1231.         { Put it into a Str255 because it's faster to add one string to the window than it is to add 16 }
  1232.         result := '';
  1233.         for index := 0 to 15
  1234.         do
  1235.             if offset + index < dataSize
  1236.             then
  1237.                 begin
  1238.                 len := length(result);
  1239.                 byte := BytePtr(ord4(dataPtr)+offset+index)^;
  1240.                 result[len+1] := gHexStr[ BSR(byte, 4) + 1];
  1241.                 result[len+2] := gHexStr[ BAND(byte, $F) + 1];
  1242.                 result[len+3] := ' ';
  1243.                 {$PUSH} {$R-} result[0] := chr(len + 3); {$POP}
  1244.                 end
  1245.             else
  1246.                 begin
  1247.                 result[len+1] := ' ';
  1248.                 result[len+2] := ' ';
  1249.                 result[len+3] := ' ';
  1250.                 {$PUSH} {$R-} result[0] := chr(len + 3); {$POP}
  1251.                 end;
  1252.         write (result, '| ');
  1253.  
  1254.         WWAddEncodedText ( Ptr(ord4(dataPtr)+offset), IntegerMax(dataSize - offset, 16));
  1255.  
  1256.         offset := offset + 16;
  1257.     end;
  1258. END;
  1259.  
  1260. PROCEDURE WWShowWindow;
  1261. begin
  1262.     ShowWindow (gDebugWindowPtr);
  1263. end;